package bnb

import (
	"fmt"
	"math"
	"math/big"
	"raymond/global"
	"strings"
)

// 手续费上限倍数(计算出的手续费在测试网上不够用)
var GasLimitMultiple uint64 = 2

type Unit int

const (
	ETHER Unit = iota
	GWEI
	WEI
	TOKEN
)

var units = []string{"ETHER", "GWEI", "WEI"}

func (u Unit) String() string {
	return units[u]
}

func (u Unit) ToWei(v interface{}) *big.Int {
	var amount *big.Int
	switch u {
	case ETHER:
		amount = toWei(v, 18)
	case GWEI:
		amount = toWei(v, 9)
	case WEI:
		amount = toWei(v, 0)
	case TOKEN:
		amount = toWei(v, 18)
	}
	return amount
}

func (u Unit) ToToken(v interface{}) string {
	var amount *big.Float
	switch u {
	case ETHER:
		amount = toDecimal(v, 0)
	case GWEI:
		amount = toDecimal(v, 9)
	case WEI:
		amount = toDecimal(v, 18)
	case TOKEN:
		amount = toDecimal(v, 0)
	}
	return fmt.Sprintf("%.18f", amount)
}

// ToDecimal wei to decimals
func toDecimal(ivalue interface{}, decimals int) *big.Float {
	value := new(big.Int)
	switch v := ivalue.(type) {
	case string:
		value.SetString(v, 10)
	case *big.Int:
		value = v
	}

	//mul := decimal.NewFromFloat(float64(10)).Pow(decimal.NewFromFloat(float64(decimals)))
	//num, _ := decimal.NewFromString(value.String())
	//result := num.Div(mul)

	amount, _ := value.Float64()
	result := new(big.Float).Quo(big.NewFloat(amount), big.NewFloat(math.Pow10(decimals)))

	return result
}

// ToWei decimals to wei
func toWei(iamount interface{}, decimals int) *big.Int {
	//amount := decimal.NewFromFloat(0)
	amount := new(big.Float)
	switch v := iamount.(type) {
	case string:
		//amount, _ = decimal.NewFromString(v)
		amount.SetString(v)
	case float32:
		amount.SetFloat64(float64(v))
	case float64:
		//amount = decimal.NewFromFloat(v)
		amount.SetFloat64(v)
	case int64:
		//amount = decimal.NewFromFloat(float64(v))
		amount.SetInt64(v)
	case int:
		//amount = decimal.NewFromFloat(float64(v))
		amount.SetInt64(int64(v))
		/*
			case decimal.Decimal:
				amount = v
			case *decimal.Decimal:
				amount = *v
		*/
	default:
		// 0
	}

	//mul := decimal.NewFromFloat(float64(10)).Pow(decimal.NewFromFloat(float64(decimals)))
	//result := amount.Mul(mul)

	// tenPow18 := new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)

	result := new(big.Float).Mul(amount, big.NewFloat(math.Pow10(decimals)))
	wei := new(big.Int)
	wei.SetString(fmt.Sprintf("%f", result), 10)

	return wei
}

// USDT
var bscUsdtDevContract = []string{strings.ToLower("0x540fA9FE8f5eF6270584D1DC5e562a9769924A82")}
var bscUsdtTestContract = []string{strings.ToLower("0x43d58716134eE123B9523A4e1c1F0C6F2c2EaFf0")}
var bscUsdtUatContract = []string{strings.ToLower("0x43d58716134eE123B9523A4e1c1F0C6F2c2EaFf0")}

// var bscUsdtMainContract = []string{strings.ToLower("0x55d398326f99059fF775485246999027B3197955")}

// BCPC
var bscBcpcTestContract = []string{strings.ToLower("0x1B396d5DeEfabB40d75d7c84c8564Af5Ab7B3FB5"), strings.ToLower("0xaDdAC1760bCDB2393d17B6f638165A78A0b62689")}
var bscBcpcMainContract = []string{strings.ToLower("0x55d398326f99059fF775485246999027B3197955")}

func GetBep20ContractList() []string {
	switch global.DEFAULT_ENV {
	case global.DEV:
		return bscBcpcTestContract
	case global.TEST:
		return bscBcpcTestContract
	case global.UAT:
		return bscBcpcTestContract
	case global.PROD:
		return bscBcpcMainContract
	}
	return bscBcpcMainContract
}
